﻿Public Class NumericTextBoxAttachedBehavior

    Private Shared _txtHost As TextBox

    Public Shared AllowOnlyDigitsProperty As DependencyProperty = DependencyProperty.RegisterAttached("AllowOnlyDigits", GetType(Boolean), GetType(NumericTextBoxAttachedBehavior), New PropertyMetadata(False, AddressOf AllowOnlyDigitsChanged))

    Public Shared Function GetIsDigitOnly(ByVal obj As DependencyObject) As Boolean
        Return CType(obj.GetValue(AllowOnlyDigitsProperty), Boolean)
    End Function

    Public Shared Sub SetIsDigitOnly(ByVal obj As DependencyObject, ByVal value As Boolean)
        obj.SetValue(AllowOnlyDigitsProperty, value)
    End Sub

    Private Shared Sub AllowOnlyDigitsChanged(ByVal sender As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        _txtHost = TryCast(sender, TextBox)

        If CType(e.NewValue, Boolean) Then
            AddHandler _txtHost.PreviewDrop, AddressOf OnDrop
            AddHandler _txtHost.PreviewDragOver, AddressOf OnDragOver
            AddHandler _txtHost.KeyDown, AddressOf OnKeyDown
        Else
            RemoveHandler _txtHost.PreviewDrop, AddressOf OnDrop
            RemoveHandler _txtHost.PreviewDragOver, AddressOf OnDragOver
            RemoveHandler _txtHost.KeyDown, AddressOf OnKeyDown
        End If
    End Sub

    Shared Sub New()
        EventManager.RegisterClassHandler(GetType(TextBox), DataObject.PastingEvent, New DataObjectPastingEventHandler(AddressOf OnPasting), True)

    End Sub 

    Private Shared Sub OnPasting(ByVal sender As Object, ByVal e As DataObjectPastingEventArgs)

        If sender IsNot _txtHost Then
            Exit Sub
        End If

        'erase the pasted value if its not numbers
        If Not IsDataValid(e.DataObject) Then
            Dim data As New DataObject()
            data.SetText(String.Empty)
            e.DataObject = data
            e.Handled = False
        End If
    End Sub

    Private Shared Sub OnDrop(ByVal sender As Object, ByVal e As DragEventArgs)
        e.Handled = Not IsDataValid(e.Data)
    End Sub

    Private Shared Sub OnDragOver(ByVal sender As Object, ByVal e As DragEventArgs)
        If Not IsDataValid(e.Data) Then
            e.Handled = True
            e.Effects = DragDropEffects.None
        End If
    End Sub

    Private Shared Function IsDataValid(ByVal data As IDataObject) As [Boolean]
        Dim bolIsValid As Boolean = False
        If data IsNot Nothing Then
            Dim text As String = TryCast(data.GetData(DataFormats.Text), String)
            If text IsNot Nothing Then
                text = text.Trim
                If text.Length > 0 Then
                    Dim intResult As Integer = -1
                    If Integer.TryParse(text, intResult) Then
                        If intResult > 0 Then
                            bolisValid = True
                        End If
                    End If
                End If
            End If
        End If
        Return bolIsValid
    End Function

    Private Shared Sub OnKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
        If e.Key = Key.Tab Then
            Exit Sub
        End If

        If e.Key < Key.D0 OrElse e.Key > Key.D9 Then
            If e.Key < Key.NumPad0 OrElse e.Key > Key.NumPad9 Then
                If e.Key <> Key.Back Then
                    e.Handled = True
                End If
            End If
        End If
    End Sub

End Class
